# -*- coding:utf-8 -*-
import os,sys
import re
import traceback
import time
from collections import deque
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), os.pardir, os.pardir))
import supeanut_config
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), os.pardir))
from CommonLib.mylog import mylog
from ExrightsTool import ExrightsTool
from TrendRecog import TrendRecog
from KlineRecog import KlineRecog
from SellStrategy import SellStrategy
from CommonLib.StockTool import StockTool

'''
作者：supeanut
创建时间：2016-xx-xx xx:xx:xx
功能描述：
相关配置：
	supeanut_config.XXX
历史改动：
	2016-xx-xx: xxxxxx
'''
class BackTest:
	def __init__(self):
		self.StockTool = StockTool()
		self.ExrightsTool = ExrightsTool()
		self.TrendRecog = TrendRecog()
		self.KlineRecog = KlineRecog()
		self.SellStrategy = SellStrategy()
		self.code_data = {}
		self.code_background = {}
		self.code_buyDatetime_Dict = {}
		self.code_sellDatetime_Dict = {}

	# 拿到需要分析的周期性数据
	def getCodesData(self, ):
		self.code_data = {}
		flag, codes = self.StockTool.get_all_stock_code('L')
		codes = codes[:300]
		#codes = ["300423"]
		period = ["2015-01-01", "2017-02-27"]
		adj_mode = "pre"
		period_mode = "day"
		for code in codes:
			flag, itemList = self.ExrightsTool.getAdjItemList(code, adj_mode, period_mode, period)
			if flag is False:
				return False, itemList
			self.code_data[code] = itemList
		return True, self.code_data

	# 获取符合某种背景的时间点
	def getBackGround(self, ):
		self.code_background = {}
		for code, itemList in self.code_data.items():
			self.code_background[code] = []
			# =============背景可重写=============
			try:
				datetime_list = self.TrendRecog.pricePos(itemList, None, [0.0, 0.35])
				self.code_background[code] = datetime_list
			except:
				return False, traceback.format_exc()
			# ====================================
		return True, self.code_background

	# 获取买入策略对应的周期点
	def getBuyDatetime(self, ):
		self.code_buyDatetime_Dict = {}
		for code, itemList in self.code_data.items():
			background = self.code_background[code]
			self.code_buyDatetime_Dict[code] = None
			# =============买入策略可重写=============
			datetime_list = []
			try:
				#datetime_list1 = self.KlineRecog.hongSanBing(itemList, 3, [0.005, 0.035], 1.0)
				datetime_list2 = self.KlineRecog.sanWuYa(itemList, 3, [0.005, 0.035], 1.0)
			except:
				return False, traceback.format_exc()
			# =============买入理由添加===============
			self.code_buyDatetime_Dict[code] = {"buyDatetime_list":[], "buyReason_dict":{}}
			'''
			for datetime in datetime_list1:
				# 添加背景限制
				if datetime not in background:
					continue
				if not self.code_buyDatetime_Dict[code]["buyReason_dict"].has_key(datetime):
					self.code_buyDatetime_Dict[code]["buyReason_dict"][datetime] = []
				self.code_buyDatetime_Dict[code]["buyReason_dict"][datetime].append("hongsanbing")
			'''
			for datetime in datetime_list2:
				if datetime not in background:
					continue
				if not self.code_buyDatetime_Dict[code]["buyReason_dict"].has_key(datetime):
					self.code_buyDatetime_Dict[code]["buyReason_dict"][datetime] = []
				self.code_buyDatetime_Dict[code]["buyReason_dict"][datetime].append("sanwuya")
			# =============买入周期点List and Sort, 加上背景限制
			for datetime in self.code_buyDatetime_Dict[code]["buyReason_dict"]:
				self.code_buyDatetime_Dict[code]["buyDatetime_list"].append(datetime)
			self.code_buyDatetime_Dict[code]["buyDatetime_list"].sort()
		return True, self.code_buyDatetime_Dict

	# 获取卖出策略对应的周期点
	def getSellDatetime(self, ):
		for code, itemList in self.code_data.items():
			self.code_sellDatetime_Dict[code] = {}
			# =============卖出策略可重写=============
			try:
				sellDatetimeDict1 = self.SellStrategy.zhiYingSun(itemList, self.code_buyDatetime_Dict[code]["buyDatetime_list"], 0.15,0.05,0.08,15,False)
			except:
				return False, traceback.format_exc()
			# =============卖出理由=============
			for buyDatetime in sellDatetimeDict1:
				if not self.code_sellDatetime_Dict[code].has_key(buyDatetime):
					self.code_sellDatetime_Dict[code][buyDatetime] = {"sellDatetime_list":[], "sellReason_dict":{}}
				if not self.code_sellDatetime_Dict[code][buyDatetime]["sellReason_dict"].has_key(sellDatetimeDict1[buyDatetime][0]):
					self.code_sellDatetime_Dict[code][buyDatetime]["sellReason_dict"][sellDatetimeDict1[buyDatetime][0]] = []
				self.code_sellDatetime_Dict[code][buyDatetime]["sellReason_dict"][sellDatetimeDict1[buyDatetime][0]].append(sellDatetimeDict1[buyDatetime][1])
			# 整理排序sellDatetime_list
			for buy_datetime in self.code_sellDatetime_Dict[code]:
				for sell_datetime in self.code_sellDatetime_Dict[code][buy_datetime]["sellReason_dict"]:
					self.code_sellDatetime_Dict[code][buy_datetime]["sellDatetime_list"].append(sell_datetime)
				self.code_sellDatetime_Dict[code][buy_datetime]["sellDatetime_list"].sort()
		return True, self.code_sellDatetime_Dict

	# 策略评价报告
	# 卖出取最近一次的卖出信号
	def strategyReport(self, ):
		PR_sum_all = 0.0
		PR_sum_len = 0
		for code, itemList in self.code_data.items():
			print code
			# 构建itemDict
			itemDict = {}
			for item in itemList:
				itemDict[item[0]] = item[1:]
			# 计算买卖收益
			buy_sell_info = []
			for buy_datetime in self.code_sellDatetime_Dict[code]:
				# 取最近一次卖出信号
				sell_datetime = min(self.code_sellDatetime_Dict[code][buy_datetime]["sellDatetime_list"])
				# 收益
				shouyi = (itemDict[sell_datetime][1] - itemDict[buy_datetime][1]) / itemDict[buy_datetime][1]
				# 买卖理由
				buy_reason = self.code_buyDatetime_Dict[code]["buyReason_dict"][buy_datetime]
				sell_reason = self.code_sellDatetime_Dict[code][buy_datetime]["sellReason_dict"][sell_datetime]
				buy_sell_info.append([buy_datetime, sell_datetime, buy_reason, sell_reason, shouyi])
			PR_sum = 0.0
			for info in buy_sell_info:
				print info
				PR_sum += info[4]
				PR_sum_all += info[4]
			if len(buy_sell_info) != 0:
				PR_avg = PR_sum / len(buy_sell_info) 
			else:
				PR_avg = 0.0
			PR_sum_len += len(buy_sell_info)
			print 'summary: PR_avg:%f'%PR_avg
		print PR_sum_all / PR_sum_len

if __name__ == '__main__':
	obj = BackTest()
	flag, msg1 = obj.getCodesData()
	print flag
	flag, msg2 = obj.getBackGround()
	print flag
	flag, msg3 = obj.getBuyDatetime()
	print flag
	flag, msg4 = obj.getSellDatetime()
	print flag
	obj.strategyReport()
